﻿/*********************************************************************************
 *Author:         OnClick
 *Version:        1.0
 *UnityVersion:   2018.3.1f1
 *Date:           2019-03-26
 *Description:    IFramework
 *History:        2018.11--
*********************************************************************************/
using System;

namespace IFramework
{
    public class DataFrameInfo
    {
        /// RSV1,RSV2,RSV3,各1位，用于扩展定义的,如果没有扩展约定的情况则必须为0
        public bool Rsv1 { get; set; }
        public bool Rsv2 { get; set; }
        public bool Rsv3 { get; set; }
        //true则该消息为消息尾部,false还有后续数据包;
        public bool IsEnd { get; set; } = true;
        public byte OpCode { get; set; } = 0x01;
        public bool Mask { get; set; } = false;// true使用掩码解析消息
        public byte[] MaskKey { get; set; }

        public long DataLength { get; set; }
        public BufferSegment Data { get; set; }
        public byte[] EncodingToBytes()
        {
            if (Data == null || Data.Buffer.LongLength != DataLength)
                throw new Exception("payload buffer error");
            if (Data.Len > 0) DataLength = Data.Len;
            long headLen = Mask ? 6 : 2;
            if (DataLength < 126) { }
            else if (DataLength >= 126 && DataLength < 127) headLen += 2;
            else if (DataLength >= 127) headLen += 8;
            byte[] buffer = new byte[headLen + DataLength];
            int pos = 0;
            buffer[pos] = (byte)(IsEnd ? 128 : 0);
            buffer[pos] += OpCode;
            buffer[++pos] = (byte)(Mask ? 128 : 0);
            if (DataLength < 0x7e) buffer[pos] += (byte)DataLength;//126
            else if (DataLength < 0xffff)//65535
            {
                buffer[++pos] = 126;
                buffer[++pos] = (byte)(buffer.Length >> 8);
                buffer[++pos] = (byte)(buffer.Length);
            }
            else
            {
                byte[] dataLengthBytes = ((ulong)DataLength).ToBytes();
                buffer[++pos] = 127;
                buffer[++pos] = dataLengthBytes[0];
                buffer[++pos] = dataLengthBytes[1];
                buffer[++pos] = dataLengthBytes[2];
                buffer[++pos] = dataLengthBytes[3];
                buffer[++pos] = dataLengthBytes[4];
                buffer[++pos] = dataLengthBytes[5];
                buffer[++pos] = dataLengthBytes[6];
                buffer[++pos] = dataLengthBytes[7];
            }
            if (Mask)
            {
                buffer[++pos] = MaskKey[0];
                buffer[++pos] = MaskKey[1];
                buffer[++pos] = MaskKey[2];
                buffer[++pos] = MaskKey[3];
                for (long i = 0; i < DataLength; ++i)
                {
                    buffer[headLen + i] = (byte)(Data.Buffer[i + Data.Offset] ^ MaskKey[i % 4]);
                }
            }
            else
            {
                for (long i = 0; i < DataLength; ++i)
                {
                    buffer[headLen + i] = Data.Buffer[i + Data.Offset];
                }
            }
            return buffer;
        }
        public bool DecodingFromBytes(BufferSegment data, bool isMaskResolve = true)
        {
            if (data.Len < 4) return false;
            int pos = data.Offset;
            IsEnd = (data.Buffer[pos] >> 7) == 1;
            OpCode = (byte)(data.Buffer[pos] & 0xf);
            Mask = (data.Buffer[++pos] >> 7) == 1;
            DataLength = (data.Buffer[pos] & 0x7f);
            //校验截取长度
            if (DataLength >= data.Len) return false;
            ++pos;
            //数据包长度超过126，需要解析附加数据
            if (DataLength < 126) { }//直接等于消息长度
            if (DataLength == 126)
            {
                DataLength = data.Buffer.ToUInt16(pos);
                pos += 2;
            }
            else if (DataLength == 127)
            {
                DataLength = (long)data.Buffer.ToUInt64(pos);
                pos += 8;
            }
            Data = new BufferSegment(data.Buffer, pos, (int)DataLength);
            //数据体
            if (Mask)
            {
                //获取掩码密钥
                MaskKey = new byte[4];
                MaskKey[0] = data.Buffer[pos];
                MaskKey[1] = data.Buffer[pos + 1];
                MaskKey[2] = data.Buffer[pos + 2];
                MaskKey[3] = data.Buffer[pos + 3];
                pos += 4;
                Data.Buffer = data.Buffer;
                Data.Offset = pos;
                if (isMaskResolve)
                {
                    long p = 0;
                    for (long i = 0; i < DataLength; ++i)
                    {
                        p = (long)pos + i;
                        Data.Buffer[p] = (byte)(Data.Buffer[p] ^ MaskKey[i % 4]);
                    }
                }
            }
            else
            {
                Data.Buffer = data.Buffer;
                Data.Offset = pos;
            }
            return true;
        }
    }

}
